package com.linsen.core.common.util;

import cn.hutool.core.codec.Base64;
import com.linsen.core.common.constant.SystemConstant;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;

/**
 * RSA非对称加密工具类
 *
 * @author zhaoyong
 * @date 2023/3/22
 */
public final class RSAUtil {
    private static final String KEY_ALGORITHM = "RSA";
    private static final int KEY_SIZE = 1024;
    public static final String RSA_TYPE = "RSA/ECB/PKCS1Padding";
    private static final String PUBLIC_KEY = SystemConstant.PUBLIC_KEY;
    private static final String PRIVATE_KEY = SystemConstant.PRIVATE_KEY;

    private RSAUtil() {
    }

    public static ArrayList<String> createRSAKeys() {
        ArrayList<String> array = new ArrayList<>();

        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            keyPairGenerator.initialize(KEY_SIZE, new SecureRandom());
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();
            String publicKeyValue = Base64.encode(publicKey.getEncoded());
            String privateKeyValue = Base64.encode(privateKey.getEncoded());
            array.add(publicKeyValue);
            array.add(privateKeyValue);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return array;
    }

    public static String getPublicKey() {
        return PUBLIC_KEY;
    }

    public static String getPrivateKey() {
        return PRIVATE_KEY;
    }

    public static PublicKey getPublicKey(String key) {
        try {
            byte[] byteKey = Base64.decode(key);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            return keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (Exception var4) {
            var4.printStackTrace();
            return null;
        }
    }

    private static PrivateKey getPrivateKey(String key) {
        try {
            byte[] byteKey = Base64.decode(key);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String encrypt(String clearText) {
        String encryptedBase64 = "";

        try {
            Key key = getPublicKey(PUBLIC_KEY);
            Cipher cipher = Cipher.getInstance(RSA_TYPE);
            cipher.init(1, key);
            byte[] encryptedBytes = cipher.doFinal(clearText.getBytes(StandardCharsets.UTF_8));
            encryptedBase64 = Base64.encode(encryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return encryptedBase64;
    }

    public static String decrypt(String encryptedBase64) {
        String decryptedString = "";

        try {
            Key key = getPrivateKey(PRIVATE_KEY);
            Cipher cipher = Cipher.getInstance(RSA_TYPE);
            cipher.init(2, key);
            byte[] encryptedBytes = Base64.decode(encryptedBase64);
            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
            decryptedString = new String(decryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return decryptedString;
    }
}
